use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{Instruction, BytecodeReader}, rtda::Frame};


#[derive(Debug, Default)]
pub struct GET_FIELD {
    index: usize
}

impl Instruction for GET_FIELD {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u16() as usize;
    }

    // 获取对象的实例变量值，然后推入操作数栈
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let cp = frame.borrow().get_method().get_class().get_constant_pool().unwrap();
        let field_ref = cp.get_constant(self.index).unwrap().field_ref();
        let field = field_ref.lock().unwrap().resolved_field();
        // 解析后的字段必须是实例字段
        if field.is_static() {
            panic!("java.lang.IncompatibleClassChangeError")
        }
        // 根据字段类型，获取相应的实例变量值
        let stack = frame.borrow().get_operand_stack();
        let _ref = stack.borrow_mut().pop_ref();
        if _ref.is_none() {
            panic!("java.lang.NullPointerException")
        }
        let _ref = _ref.unwrap();
        let descriptor = field.get_descriptor();
        let slot_id = field.get_slot_id(); // 要获取值的位置
        // let mut ref_mut = _ref.borrow_mut();
        let slots = unsafe { &mut *_ref }.get_fields_mut();
        // 推入操作数栈
        match &descriptor[..1] {
            "Z" | "B"  | "C" | "S" | "I" => stack.borrow_mut().push_int(slots.get_int(slot_id)),
            "F" => stack.borrow_mut().push_float(slots.get_float(slot_id)),
            "J" => stack.borrow_mut().push_long(slots.get_long(slot_id)),
            "D" => stack.borrow_mut().push_double(slots.get_double(slot_id)),
            "L" | "[" => stack.borrow_mut().push_ref(slots.get_ref(slot_id)),
            _ => ()
        }
    }


}
